package com.icez.starbar

import android.content.Context
import android.graphics.*
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.annotation.Nullable


/**
 *
 * 类名：StarBar
 * 作者： 冰
 * 创建日期： 2018/9/9 0009 15:13
 * 描述：自定义星星
 *
 */
class StarBar @JvmOverloads constructor(//上下文
    context: Context, @Nullable attrs: AttributeSet? = null, defStyleAttr: Int = 0
) :
    View(context, attrs, defStyleAttr) {
    //星星的间距
    private var starDistance = 0

    //星星的数量
    private var starCount = 0

    //星星的大小,宽高
    private var starSize = 0

    //评分星星,精确0.1
    private var starMark = 0f

    //亮星星
    private var starFillBitmap: Bitmap? = null

    //暗星星
    private var starEmptyDrawable: Drawable? = null

    //绘制星星的画笔
    private var paint: Paint? = null

    //是否是整型
    private var integerMark = false

    //是否开启触屏
    private var isTouch = false

    //星星改变监听
    private var onStarChangeListener: OnStarChangeListener? =
        null

    private fun init(attrs: AttributeSet?) {
        //设置可点击
        isClickable = true
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatingBar)
        //设置星星的间距，默认10px
        starDistance = typedArray.getDimension(
            R.styleable.RatingBar_starDistance,
            10f
        )
            .toInt()
        //是否触屏
        isTouch = typedArray.getBoolean(R.styleable.RatingBar_isTouch, false)
        //设置星星的宽高大小,默认20px
        starSize = typedArray.getDimension(
            R.styleable.RatingBar_starSize,
            20f
        )
            .toInt()
        //设置星星的大小，默认5个
        starCount = typedArray.getInteger(R.styleable.RatingBar_starCount, 5)
        //设置空图片
        starEmptyDrawable = typedArray.getDrawable(R.styleable.RatingBar_starEmpty)
        val starFillDrawable = typedArray.getDrawable(R.styleable.RatingBar_starFill)
        //设置填充图片
        starFillBitmap = drawableToBitmap(
            starFillDrawable,
            starSize, starSize
        )
        //释放内存
        typedArray.recycle()

        //画笔
        paint = Paint()
        //设置抗锯齿
        paint!!.isAntiAlias = true
        //设置着色器 颜色延申
        paint!!.shader =
            BitmapShader(starFillBitmap!!, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
    }

    fun drawableToBitmap(
        drawable: Drawable?,
        width: Int,
        height: Int,
        config: Bitmap.Config? = Bitmap.Config.ARGB_8888
    ): Bitmap? {
        if (drawable == null) {
            return null
        }
        //创建位图，高清
        val bitmap = Bitmap.createBitmap(width, height, config!!)
        //在位图中创建画布
        val canvas = Canvas(bitmap)
        //画布的范围充满位图
        drawable.setBounds(0, 0, width, height)
        //绘制画图
        drawable.draw(canvas)
        return bitmap
    }

    /**
     * 设置是否整数评分
     * @param integerMark
     */
    fun setIntegerMark(integerMark: Boolean) {
        this.integerMark = integerMark
    }

    /**
     * 设置显示得信心分数
     * @param mark
     */
    fun setStarMark(mark: Float) {
        starMark = if (integerMark) {
            //向上空
            Math.ceil(mark.toDouble()).toFloat()
        } else {
            Math.round(mark * 10) * 1.0f / 10
        }
        invalidate()
        onStarChangeListener?.onStarChange(starMark)
    }

    /**
     * 获取星星得数量
     * @return
     */
    fun getStarMark(): Float {
        return starMark
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        //计算控件大小
        setMeasuredDimension(starSize * starCount + starDistance * (starCount - 1), starSize)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        if (starFillBitmap == null || starEmptyDrawable == null) {
            return
        }
        for (i in 0 until starCount) {
            starEmptyDrawable!!.setBounds(
                (starDistance + starSize) * i,
                0,
                (starDistance + starSize) * i + starSize,
                starSize
            )
            starEmptyDrawable!!.draw(canvas)
        }
        if (starMark > 1) {
            canvas.drawRect(0f, 0f, starSize.toFloat(), starSize.toFloat(), paint!!)
            if (starMark - starMark.toInt() == 0f) { //整数
                var i = 1
                while (i < starMark) {
                    canvas.translate((starDistance + starSize).toFloat(), 0f)
                    canvas.drawRect(0f, 0f, starSize.toFloat(), starSize.toFloat(), paint!!)
                    i++
                }
            } else {
                var i = 1
                while (i < starMark - 1) {
                    canvas.translate((starDistance + starSize).toFloat(), 0f)
                    canvas.drawRect(0f, 0f, starSize.toFloat(), starSize.toFloat(), paint!!)
                    i++
                }
                canvas.translate((starDistance + starSize).toFloat(), 0f)
                canvas.drawRect(
                    0f,
                    0f,
                    starSize * (Math.round((starMark - starMark.toInt()) * 10) * 1.0f / 10),
                    starSize.toFloat(),
                    paint!!
                )
            }
        } else {
            canvas.drawRect(0f, 0f, starSize * starMark, starSize.toFloat(), paint!!)
        }
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!isTouch) {
            return super.onTouchEvent(event)
        }
        var x = event.x.toInt()
        if (x < 0) {
            x = 0
        }
        if (x > measuredWidth) {
            x = measuredWidth
        }
        when (event.action) {
            MotionEvent.ACTION_DOWN -> setStarMark(x * 1.0f / (measuredWidth * 1.0f / starCount))
            MotionEvent.ACTION_MOVE -> {

                setStarMark(x * 1.0f / (measuredWidth * 1.0f / starCount))
            }
            MotionEvent.ACTION_UP -> {
            }
            MotionEvent.ACTION_OUTSIDE -> {
            }
        }
        invalidate()
        return super.onTouchEvent(event)
    }

    /**
     * 星星监听
     */
    interface OnStarChangeListener {
        fun onStarChange(mark: Float)
    }

    /**
     * 设置星星改变监听
     * @param onStarChangeListener
     */
    fun setOnStarChangeListener(onStarChangeListener: OnStarChangeListener?) {
        this.onStarChangeListener = onStarChangeListener
    }

    init {
        init(attrs)
    }
}